﻿using System;
using System.Collections.Generic;
using System.IO;
using RayDen.Library.Components;
using RayDen.Library.Components.Color;
using RayDen.Library.Components.SystemComponents;
using RayDen.Library.Core.Primitives;
using RayDen.Library.Data.Xml;
using RayDen.Library.Entity;

namespace RayDen.RayEngine {
    public class GlobalConfiguration : ConfigurableEntity 
    {
        protected static readonly GlobalConfiguration instance = new GlobalConfiguration();

        public static GlobalConfiguration Instance {
            get
            {
                return instance;
            }
        }
        public bool LowLatency { get; set; }

        public int SpectralSamplesCount { get; set; }
        public bool SpectralRendering { get; set; }

        public bool ToneMapping { get; set; }

        public float LinearToneMapValue { get; set; }

        public bool FilterImage { get; set; }

        public int FilterType { get; set; }

        public bool UseSceneCaching { get; set; }

        public bool AdaptiveFilm { get; set; }

        public string SceneCacheDirectory { get; set; }

        public RenderingEngines Engine { get; set; }

        /// <summary>
        /// 0 - Uniform Sampler
        /// 1 - Low Discrepancy Sampler
        /// 2 - Halton Sampler
        /// 3 - Adaptive Tile Sampler
        /// </summary>
        public int SamplerType { get; set; }

        public int ToneMapType { get; set; }
        public string ToneMapParams { get; set; }

        public bool PrintMaterials { get; set; }


        public GlobalConfiguration()
        {
            ReadValues();
        }

        public void ReadValues()
        {
            UseSceneCaching = Get("Caching", false);
            SceneCacheDirectory = Get("Caching.Path", @"F:\Dev\Temp\SceneCache\");
            SpectralSamplesCount = Get("Renderer.SpectralSamplesCount", 8);
            SpectralRendering = Get("Renderer.Spectral", false);
            RadianceFactory.SpectralSampling = SpectralRendering;
            ToneMapping = Get("Image.ToneMap", false);
            FilterImage = Get("Image.Filtering", false);
            FilterType = Get("Image.FilterType", 0);
            LinearToneMapValue = Get("Image.LinearToneMapValue", 1.5f);
            Engine = Get("Renderer.Engine", RenderingEngines.Direct);
            AdaptiveFilm = Get("AdaptiveFilm", false);
            this.SamplerType = Get("SamplerType", 1);
            this.ToneMapType = Get("Image.ToneMapType", 0);
            this.ToneMapParams = Get("Image.ToneMapParams", "1.0");
        }

        public void OpenConfig(string path) {
            Tracer.TraceLine("Reading configuration {0}", path);

            using (var frameFile = new FileStream(path, FileMode.Open, FileAccess.Read)) {
                using (var reader = new StreamReader(frameFile)) {
                    var entity = (Dictionary<string, object>)SerializationService.Deserialize(reader.ReadToEnd(), typeof(Dictionary<string, object>), new[] { typeof(RenderingEngines), typeof(string[]) });
                    foreach (var item in entity) {
                        if (this.items.ContainsKey(item.Key)) {
                            this.items[item.Key] = item.Value;
                        }
                        else {
                            this.Add(item.Key, item.Value);
                        }
                    }
                }
            }
            this.ReadValues();
            Tracer.TraceLine("Readed");
        }

        public void SaveConfig(string path) {
            Tracer.TraceLine("Writing configuration {0}", path);
            using (var frameFile = new FileStream(path, FileMode.Truncate, FileAccess.Write)) {
                using (var writer = new StreamWriter(frameFile)) {
                    writer.WriteLine("<?xml version=\"1.0\" encoding=\"utf-8\" ?>");
                    var data = SerializationService.Serialize(this.items, new[] { typeof(RenderingEngines), typeof(Array), typeof(string[])});
                    writer.Write(data);
                }
            }
            Tracer.TraceLine("Written");
        }


    }
}
